package com.cmic.rcs.emoji.controller.web;

import com.cmic.rcs.emoji.common.Constant;
import com.cmic.rcs.emoji.entity.dto.ChangePasswordRequest;
import com.cmic.rcs.emoji.entity.dto.LoginRequest;
import com.cmic.rcs.emoji.entity.dto.VerifyRequest;
import com.cmic.rcs.emoji.entity.vo.AdminLoginResponse;
import com.cmic.rcs.emoji.entity.vo.CaptchaResponse;
import com.cmic.rcs.emoji.service.ITAdminService;
import com.cmic.rcs.emoji.util.CaptchaUtils;
import com.cmic.rcs.emoji.util.CommonUtils;
import com.cmic.rcs.enhance.message.g5.core.common.Response;
import com.cmic.rcs.enhance.message.g5.core.common.ResponseData;
import com.cmic.rcs.enhance.message.g5.core.common.ReturnCodeEnum;
import com.fasterxml.jackson.core.JsonProcessingException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.concurrent.TimeUnit;

import static com.cmic.rcs.emoji.common.Constant.CAPTCHA_EXPIRE_TIME_SECONDS;
import static com.cmic.rcs.emoji.common.Constant.REDIS_CAPTCHA_KEY_PREFIX;

/**
 * 认证控制器
 *
 * @author
 */
@Slf4j
@RestController
@RequestMapping("/api/web/auth")
public class AuthController {


    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private ITAdminService adminService;

    /**
     * 获取图形验证码
     *
     * @return 验证码信息
     */
    @PostMapping("/captcha")
    public ResponseData<?> generateCaptcha() {
        log.info("获取验证码");
        try {
            // 生成验证码
            String code = CaptchaUtils.generateCode();
            // 创建验证码图片
            String imageBase64 = CaptchaUtils.createCaptchaImage(code);
            // 保存验证码到redis  设置过期时间为300秒
            String captchaKey = CommonUtils.getUuid();

            redisTemplate.opsForValue().set(REDIS_CAPTCHA_KEY_PREFIX + captchaKey, code, CAPTCHA_EXPIRE_TIME_SECONDS, TimeUnit.SECONDS);
            CaptchaResponse captchaResponse = new CaptchaResponse();
            captchaResponse.setCaptchaKey(captchaKey);
            captchaResponse.setCaptchaImage(imageBase64);
            return ResponseData.OK(captchaResponse);
        } catch (Exception e) {
            log.error("获取验证码失败: {}", e.toString(), e);
            // 返回空验证码信息
            return ResponseData.OK(new CaptchaResponse());
        }
    }

    /**
     * 验证验证码
     *
     * @param request 验证请求
     * @return 验证结果
     */
    @PostMapping("/verify")
    public ResponseData<?> verifyCaptcha(@RequestBody VerifyRequest request) {
        log.info("验证验证码");
        // 验证参数
        String captchaId = request.getCaptchaKey();
        String captcha = request.getCaptchaCode();
        // 验证参数不能为空
        if (StringUtils.isEmpty(captchaId) || StringUtils.isEmpty(captcha)) {
            return new ResponseData<>(ReturnCodeEnum.MVC_EXCEPTION);
        }
        // 从redis获取验证码
        String redisKey = REDIS_CAPTCHA_KEY_PREFIX + captchaId;
        String storedCode = redisTemplate.opsForValue().get(redisKey);
        if (storedCode == null) {
            return new ResponseData<>(ReturnCodeEnum.VERIFICATION_EXPIRED);
        }
        // 验证验证码
        if (!CaptchaUtils.validateCode(captcha, storedCode)) {
            return new ResponseData<>(ReturnCodeEnum.VERIFICATION_ERROR);
        }
        // 验证成功后，删除验证码，防止重复使用
        redisTemplate.delete(redisKey);
        // 返回空数据的成功响应，确保类型一致性
        return ResponseData.OK("验证码验证成功");
    }

    /**
     * 刷新验证码
     *
     * @param captchaKey 验证码key
     * @return 新的验证码信息
     */
    @PostMapping("/refresh/{captchaKey}")
    public ResponseData<?> refreshCaptcha(@PathVariable String captchaKey) {
        log.info("刷新验证码");
        // 验证参数不能为空
        if (StringUtils.isEmpty(captchaKey)) {
            return ResponseData.OK(new CaptchaResponse());
        }
        try {
            // 删除旧验证码
            String redisKey = REDIS_CAPTCHA_KEY_PREFIX + captchaKey; // 验证码redis key
            redisTemplate.delete(redisKey);
            // 生成新验证码
            String code = CaptchaUtils.generateCode();
            // 创建验证码图片
            String imageBase64 = CaptchaUtils.createCaptchaImage(code);
            // 保存新验证码到redis  设置过期时间为300秒
            redisTemplate.opsForValue().set(REDIS_CAPTCHA_KEY_PREFIX + captchaKey, code, CAPTCHA_EXPIRE_TIME_SECONDS, TimeUnit.SECONDS);
            CaptchaResponse captchaResponse = new CaptchaResponse();
            captchaResponse.setCaptchaKey(captchaKey);
            captchaResponse.setCaptchaImage(imageBase64);
            return ResponseData.OK(captchaResponse);
        } catch (Exception e) {
            log.error("刷新验证码失败: {}", e.toString(), e);
            return ResponseData.OK(new CaptchaResponse());
        }
    }

    /**
     * 管理员登录
     * @param request 登录请求
     * @return 登录结果
     */
    @PostMapping("/login")
    public Response login(@RequestBody LoginRequest request, HttpSession session, HttpServletResponse response) throws JsonProcessingException {

        try {
            log.info("管理员登录");
            // 登录
            AdminLoginResponse loginResponse = adminService.login(request);
            // 保存登录信息到session
            session.setAttribute("adminName", loginResponse.getAdminName());
            session.setAttribute("adminAccount", loginResponse.getAdminAccount());
            //设置session过期时间 30分钟
            session.setMaxInactiveInterval((int) Constant.SESSION_EXPIRE_TIME_SECONDS);
            log.info("登录成功: {}", loginResponse);

            // 检查是否需要密码过期提示
            if (loginResponse.getPasswordExpireDays() != null) {
                if (loginResponse.getPasswordExpireDays() <= 0) {
                    // 密码已过期
                    return  ResponseData.Error(ReturnCodeEnum.PASSWORD_EXPIRED);
                } else if (loginResponse.getPasswordExpireDays() <= Constant.PASSWORD_WARNING_DAYS) {
                    // 密码即将过期，返回警告信息
                    ResponseData<AdminLoginResponse> responseData = new ResponseData<>(ReturnCodeEnum.PASSWORD_WILL_EXPIRE, loginResponse);
                    responseData.setMsg("密码即将过期，剩余" + loginResponse.getPasswordExpireDays() + "天");
                    return responseData;
                }
            }
            // 设置响应头，包含会话过期时间
            response.setHeader(Constant.SESSION_EXPIRE_HEADER, String.valueOf(System.currentTimeMillis() + Constant.SESSION_EXPIRE_TIME_SECONDS * 1000)); // 设置响应头，delay 30分钟过期



            return ResponseData.OK(loginResponse);
        } catch (RuntimeException e) {
            log.error("登录失败: {}", e.getMessage());
            // 根据异常信息返回不同的错误码
            if (e.getMessage().contains("账号已被锁定")) {
                return  ResponseData.Error(ReturnCodeEnum.ACCOUNT_LOCKED);
            } else if (e.getMessage().contains("密码已过期")) {
                return  ResponseData.Error(ReturnCodeEnum.PASSWORD_EXPIRED);
            } else if (e.getMessage().contains("密码错误")) {
                return  ResponseData.Error(ReturnCodeEnum.PASSWORD_ERROR);
            } else if (e.getMessage().contains("管理员不存在")) {
                return  ResponseData.Error(ReturnCodeEnum.ADMIN_NOT_EXIST);
            } else if (e.getMessage().contains("账号已被禁用")) {
                return  ResponseData.Error(ReturnCodeEnum.ACCOUNT_DISABLED);
            }
            return  ResponseData.Error(ReturnCodeEnum.LOGIN_FAILED);
        }catch (Exception e){
            log.error("登录失败: {}", e.getMessage());
            return ResponseData.Error(ReturnCodeEnum.SYSTEM_ERROR);
        }

    }


    /**
     * 管理员注销
     * @param session session
     * @param request request
     * @param response response
     * @return 登出结果
     */
    @PostMapping("/admin/logout")
    public ResponseData<?> logout(HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        log.info("管理员注销");
        try {
            // 清除session中的登录信息
            session.invalidate();

            // 清除会话ID Cookie
            String sessionIdCookieName = Constant.SESSION_ID_COOKIE_NAME;
            jakarta.servlet.http.Cookie[] cookies = request.getCookies();
            if (cookies != null) {
                for (jakarta.servlet.http.Cookie cookie : cookies) {
                    if (sessionIdCookieName.equals(cookie.getName())) {
                        cookie.setValue(null);
                        cookie.setPath("/");
                        cookie.setMaxAge(0);
                        response.addCookie(cookie);
                        break;
                    }
                }
            }

            log.info("注销成功");
            return ResponseData.OK("注销成功");
        } catch (Exception e) {
            log.error("注销失败: {}", e.toString(), e);
            return (ResponseData<?>) ResponseData.Error(ReturnCodeEnum.LOGOUT_FAILED);
        }

    }
    /**
     * 修改管理员密码
     * @param request 修改密码请求参数
     * @param session HttpSession对象，用于获取当前登录用户信息
     * @return 修改结果
     */
    @PostMapping("/admin/change-password")
    public Response changePassword(@RequestBody ChangePasswordRequest request, HttpSession session) {
        try {
            log.info("修改管理员密码请求");

            // 从session中获取当前登录的管理员账号
            Object adminAccountObj = session.getAttribute("adminAccount");
            if (adminAccountObj == null) {
                return  ResponseData.Error(ReturnCodeEnum.USER_NOT_LOGIN);
            }

            String adminAccount = adminAccountObj.toString();

            // 调用服务层修改密码
            adminService.changePassword(adminAccount, request);

            return ResponseData.OK("密码修改成功");
        } catch (RuntimeException e) {
            log.error("修改密码失败: {}", e.getMessage());
            // 根据异常信息返回不同的错误码
            if (e.getMessage().contains("管理员不存在")) {
                return ResponseData.Error(ReturnCodeEnum.ADMIN_NOT_EXIST);
            } else if (e.getMessage().contains("管理员状态异常")) {
                return ResponseData.Error(ReturnCodeEnum.ACCOUNT_DISABLED);
            } else if (e.getMessage().contains("当前密码错误")) {
                return ResponseData.Error(ReturnCodeEnum.PASSWORD_ERROR);
            } else if (e.getMessage().contains("两次输入的新密码不一致")) {
                return ResponseData.Error(ReturnCodeEnum.PASSWORD_NOT_MATCH);
            } else if (e.getMessage().contains("新密码不能与旧密码相同")) {
                return ResponseData.Error(ReturnCodeEnum.NEW_PASSWORD_SAME_AS_OLD);
            }
            return ResponseData.Error(ReturnCodeEnum.SYSTEM_ERROR);
        } catch (Exception e) {
            log.error("修改密码失败: {}", e.getMessage(), e);
            return ResponseData.Error(ReturnCodeEnum.SYSTEM_ERROR);
        }

    }

}
